1
2
3
4
5
6
7 package ca.uhn.cache.util;
8
9 import java.util.NoSuchElementException;
10
11 import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
12 import ca.uhn.cache.util.exception.MutableIteratorException;
13
14 /***
15 * Default implementation of IMutableIterator. The default
16 * close() method does nothing, and should be overridden to perform any
17 * required cleanup.
18 *
19 * Note that this class is NOT thread-safe in the sense of supporting multiple
20 * iterating clients or competing threads calling add and freeze (although
21 * different threads may add and iterate concurrently). It is assumed that one
22 * thread is iterating. It is up to the caller to ensure that freeze() is not called
23 * until after add() has been called as for the last time.
24 *
25 * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
26 * @version $Revision: 1.1 $ updated on $Date: 2005/01/26 00:25:50 $ by $Author: bryan_tripp $
27 */
28 public class MutableIterator implements IMutableIterator {
29
30 private LinkedQueue myQueue;
31 private Object myNext;
32 private MutableIteratorException myException;
33 private boolean myIsFrozen = false;
34
35 /***
36 * New instance.
37 */
38 public MutableIterator() {
39 myQueue = new LinkedQueue();
40 }
41
42 /***
43 * @see ca.uhn.cache.IMutableIterator#add(java.lang.Object)
44 */
45 public synchronized void add(Object theObject) {
46 if (myIsFrozen) {
47 throw new IllegalStateException("Can't add to a frozen IMutableIterator");
48 }
49
50 try {
51 myQueue.put(theObject);
52 } catch (InterruptedException e) {
53 declareException(e);
54 }
55 }
56
57 /***
58 * @see ca.uhn.cache.IMutableIterator#freeze()
59 */
60 public synchronized void freeze() {
61 myIsFrozen = true;
62
63 try {
64 myQueue.put(new EndMarker());
65 } catch (InterruptedException e) {
66 declareException(e);
67 }
68 }
69
70 /***
71 * @see java.util.Iterator.hasNext()
72 */
73 public boolean hasNext() throws MutableIteratorException {
74 if (myException != null) {
75 throw myException;
76 }
77
78 while (myNext == null) {
79 try {
80 myNext = myQueue.poll(1);
81 } catch (InterruptedException e) {
82
83 }
84 }
85
86 boolean done = (myNext instanceof EndMarker);
87 if (done) {
88 close();
89 }
90
91 return !done;
92 }
93
94 /***
95 * @see java.util.Iterator#next()
96 */
97 public Object next() throws MutableIteratorException, NoSuchElementException {
98 if (myException != null) {
99 throw myException;
100 }
101
102 if (!hasNext()) {
103 throw new NoSuchElementException("No further items are available");
104 }
105
106 Object next = myNext;
107 myNext = null;
108
109 return next;
110 }
111
112 /***
113 * Does nothing by default. Override if you need to do more.
114 *
115 * @see ca.uhn.cache.IMutableIterator#close()
116 */
117 public void close() {
118 }
119
120 /***
121 * @see ca.uhn.cache.IMutableIterator#declareException(java.lang.Exception)
122 */
123 public void declareException(Exception theException) {
124 myException = new MutableIteratorException(theException);
125 }
126
127 /***
128 * @see java.util.Iterator#remove()
129 */
130 public void remove() {
131 throw new UnsupportedOperationException(
132 "Remove has no meaning here as this iterator isn't tied to a specific source");
133 }
134
135 /***
136 * Marker added to queue on finish(). Could set a finished flag, but this might be
137 * out of order due to threading.
138 *
139 * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
140 * @version $Revision: 1.1 $ updated on $Date: 2005/01/26 00:25:50 $ by $Author: bryan_tripp $
141 */
142 private static class EndMarker {
143 }
144
145 }